package org.jeecg.modules.zixishi.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.modules.order.entity.Order;
import org.jeecg.modules.order.mapper.OrderMapper;
import org.jeecg.modules.order.service.IOrderService;
import org.jeecg.modules.recharge.mapper.OrderRechargeMapper;
import org.jeecg.modules.system.mapper.SysLogMapper;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.jeecg.modules.zixishi.entity.Quyu;
import org.jeecg.modules.zixishi.entity.SwiperPic;
import org.jeecg.modules.zixishi.entity.Zixishi;
import org.jeecg.modules.zixishi.mapper.QuyuMapper;
import org.jeecg.modules.zixishi.mapper.SwiperPicMapper;
import org.jeecg.modules.zixishi.mapper.ZixishiMapper;
import org.jeecg.modules.zixishi.service.IAnalysisService;
import org.jeecg.modules.zixishi.service.IZixishiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 自习室
 * @Author: jeecg-boot
 * @Date:   2024-05-19
 * @Version: V1.0
 */
@Service
public class AnalysisServiceImpl extends ServiceImpl<OrderMapper, Order> implements IAnalysisService {

	@Autowired
	private SysLogMapper sysLogMapper;
	@Autowired
	private OrderMapper orderMapper;
	@Autowired
	private OrderRechargeMapper orderRechargeMapper;
	@Autowired
	private SysUserMapper sysUserMapper;

	public Map orderAnalysis(Date dayStart, Date dayEnd){
		Map retMap = new HashMap<>();
		int days = (int)DateUtil.betweenDay(dayStart,dayEnd,true);
		Calendar calendar = new GregorianCalendar();
		calendar.setTime(dayStart);
		calendar.add(Calendar.DAY_OF_MONTH, (0-days));
		Date preDayStart = calendar.getTime();

		//用户登录数
		Long visCnt = sysLogMapper.findTodayVisitCount(dayStart,dayEnd);
		Long preVisCnt = sysLogMapper.findTodayVisitCount(preDayStart,dayStart);
		Map visMap = new HashMap();
		visMap.put("visCnt",visCnt);
		Double percent = mom(visCnt,preVisCnt);
		visMap.put("percent",String.format("%.2f",percent*100));
		visMap.put("add",percent>0);
		retMap.put("visMap",visMap);

		//访问用户数
		Long userCnt = sysLogMapper.findTodayUserCount(dayStart,dayEnd);
		Long preUserCnt = sysLogMapper.findTodayUserCount(preDayStart,dayStart);
		Map userMap = new HashMap();
		userMap.put("userCnt",userCnt);
		Double userPercent = mom(userCnt,preUserCnt);
		userMap.put("percent",String.format("%.2f",userPercent*100));
		userMap.put("add",userPercent>0);
		retMap.put("userMap",userMap);
		//座位订单数
		Long orderTotalCnt = orderMapper.selectCount(new LambdaQueryWrapper<Order>().ge(Order::getCreateTime,dayStart).le(Order::getCreateTime,dayEnd));
		Long preOrderTotalCnt = orderMapper.selectCount(new LambdaQueryWrapper<Order>().ge(Order::getCreateTime,preDayStart).le(Order::getCreateTime,dayStart));
		Map orderMap = new HashMap();
		orderMap.put("orderTotalCnt",orderTotalCnt);
		Double orderPercent = mom(orderTotalCnt,preOrderTotalCnt);
		orderMap.put("percent",String.format("%.2f",orderPercent*100));
		orderMap.put("add",orderPercent>0);
		retMap.put("orderMap",orderMap);

		//座位订单支付数
		Long orderPaylCnt = orderMapper.selectCount(new LambdaQueryWrapper<Order>().ge(Order::getPayTime,dayStart).le(Order::getPayTime,dayEnd));
		Long preOrderPayCnt = orderMapper.selectCount(new LambdaQueryWrapper<Order>().ge(Order::getPayTime,preDayStart).le(Order::getPayTime,dayStart));
		Map orderPaylMap = new HashMap();
		orderPaylMap.put("orderPaylCnt",orderPaylCnt);
		Double orderPayPercent = mom(orderPaylCnt,preOrderPayCnt);
		orderPaylMap.put("percent",String.format("%.2f",orderPayPercent*100));
		orderPaylMap.put("add",orderPayPercent>0);
		retMap.put("orderPayMap",orderPaylMap);

		//微信支付金额
		//余额支付金额
		//卡券支付金额
		List<Map> amtList = orderMapper.orderAmtByPayType(dayStart,dayEnd);
		Map amtMap = new HashMap();
		for(Map map:amtList){
			if(map != null) {
				amtMap.put("" + map.get("payType"), "" + map.get("totalAmt"));
			}
		}
		List<Map> preAmtList = orderMapper.orderAmtByPayType(preDayStart,dayStart);
		Map preAmtMap = new HashMap();
		for(Map map:amtList){
			if(map != null) {
				preAmtMap.put("" + map.get("payType"),"" + map.get("totalAmt"));
			}
		}
		Object wxObj = amtMap.get("0");
		wxObj = "null".equals("" + wxObj) ? "0" : wxObj;
		Double wxAmt = Double.parseDouble("" + wxObj);
		Object prewxObj = preAmtMap.get("0");
		prewxObj = "null".equals("" + prewxObj) ? "0" : prewxObj;
		Double prewxAmt = Double.parseDouble("" + prewxObj);
		Map wxMap = new HashMap();
		wxMap.put("wxAmt",String.format("%.2f",wxAmt));
		Double wxAmtPercent = mom(wxAmt.longValue(),prewxAmt.longValue());
		wxMap.put("percent",String.format("%.2f",wxAmtPercent*100));
		wxMap.put("add",wxAmtPercent>0);
		retMap.put("wxMap",wxMap);

		Object balbj = amtMap.get("1");
		balbj = "null".equals("" + balbj) ? "0" : balbj;
		Double balAmt = Double.parseDouble("" + balbj);
		Object prebalObj = preAmtMap.get("1");
		prebalObj = "null".equals("" + prebalObj) ? "0" : prebalObj;
		Double prebalAmt = Double.parseDouble("" + prebalObj);
		Map balanceMap = new HashMap();
		balanceMap.put("balAmt",String.format("%.2f",balAmt));
		Double balAmtPercent = mom(balAmt.longValue(),prebalAmt.longValue());
		balanceMap.put("percent",String.format("%.2f",balAmtPercent*100));
		balanceMap.put("add",balAmtPercent>0);
		retMap.put("balanceMap",balanceMap);

		Object coupobj = amtMap.get("2");
		coupobj = "null".equals("" + coupobj) ? "0" : coupobj;
		Double coupAmt = Double.parseDouble("" + coupobj);
		Object precoupObj = preAmtMap.get("2");
		precoupObj = "null".equals("" + precoupObj) ? "0" : precoupObj;
		Double precoupAmt = Double.parseDouble("" + precoupObj);
		Map coupMap = new HashMap();
		coupMap.put("coupAmt",String.format("%.2f",coupAmt));
		Double coupAmtPercent = mom(coupAmt.longValue(),precoupAmt.longValue());
		coupMap.put("percent",String.format("%.2f",coupAmtPercent*100));
		coupMap.put("add",coupAmtPercent>0);
		retMap.put("coupMap",coupMap);

		//优惠券支付金额
		Long voucherAmt = orderMapper.voucherAmt(dayStart,dayEnd);
		Long preVoucherAmt = orderMapper.voucherAmt(preDayStart,dayStart);
		voucherAmt = voucherAmt == null?0:voucherAmt;
		preVoucherAmt = preVoucherAmt == null?0:preVoucherAmt;
		Map voucherMap = new HashMap();
		voucherMap.put("voucherAmt",String.format("%.2f",voucherAmt.doubleValue()));
		Double voucherAmtPercent = mom(voucherAmt,preVoucherAmt);
		voucherMap.put("percent",String.format("%.2f",voucherAmtPercent*100));
		voucherMap.put("add",voucherAmtPercent>0);
		retMap.put("voucherMap",voucherMap);

		//退款金额
		//退款订单数
		List<Map> backList = orderMapper.backInfo(dayStart,dayEnd);
		List<Map> preBackList = orderMapper.backInfo(preDayStart,dayStart);
		Map backMap = new HashMap();
		if(CollectionUtil.isNotEmpty(backList)){
			backMap = backList.get(0);
		}
		Map preBackMap = new HashMap();
		if(CollectionUtil.isNotEmpty(preBackList)){
			preBackMap = preBackList.get(0);
		}
		Object backCntObj = backMap.get("cnt");
		backCntObj = "null".equals("" + backCntObj) ? "0" : backCntObj;
		Object backAmtObj = backMap.get("amt");
		backAmtObj = "null".equals("" + backAmtObj) ? "0" : backAmtObj;

		Object prebackCntObj = preBackMap.get("cnt");
		prebackCntObj = "null".equals("" + prebackCntObj) ? "0" : prebackCntObj;
		Object prebackAmtObj = preBackMap.get("amt");
		prebackAmtObj = "null".equals("" + prebackAmtObj) ? "0" : prebackAmtObj;

		Double backCnt = Double.parseDouble("" + backCntObj);
		Double backAmt = Double.parseDouble("" + backAmtObj);
		Double preBackCnt = Double.parseDouble("" + prebackCntObj);
		Double preBackAmt = Double.parseDouble("" + prebackAmtObj);
		Map backCntMap = new HashMap();
		backCntMap.put("cnt",String.format("%.0f",backCnt));
		Double backCntPercent = mom(backCnt.longValue(),preBackCnt.longValue());
		backCntMap.put("percent",String.format("%.2f",backCntPercent*100));
		backCntMap.put("add",backCntPercent>0);
		retMap.put("backCntMap",backCntMap);

		Map backAmtMap = new HashMap();
		backAmtMap.put("amt",String.format("%.2f",backAmt));
		Double backAmtPercent = mom(backAmt.longValue(),preBackAmt.longValue());
		backAmtMap.put("percent",String.format("%.2f",backAmtPercent*100));
		backAmtMap.put("add",backAmtPercent>0);
		retMap.put("backAmtMap",backAmtMap);

		return retMap;
	}

	public List<Map> orderCharts(Date dayStart, Date dayEnd) {
		Map<String,Map> chartMap = new HashMap();
		//每天访问量
		//每天订单支付金额
		List<Map<String,Object>> visitList = sysLogMapper.findVisitCount(dayStart,dayEnd,"mysql");
		List<Map> amtList = orderMapper.findOrderAmt(dayStart,dayEnd);
		if(null == visitList){
			visitList = new ArrayList<>();
		}
		if(null == amtList){
			amtList = new ArrayList<>();
		}
		for(Map visit:visitList){
			Map map = new HashMap();
			String type = (String) visit.get("type");
			map.put("type",type);
			map.put("tian",visit.get("tian"));
			map.put("visit",visit.get("visit").toString());
			chartMap.put(type,map);
		}
		for(Map amt:amtList){
			String type = amt.get("type").toString();
			Map map = (Map)chartMap.get(type);
			if(null == map){
				map = new HashMap();
				map.put("type",type);
				map.put("tian",amt.get("tian").toString());
				map.put("visit","0");
				chartMap.put(type,map);
			}
			map.put("amt","" + amt.get("orderMoney"));
		}
		List<Map> chartList = chartMap.values().stream().sorted((e1,e2)->{
			try {
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				Date d1 = sdf.parse("" + e1.get("tian"));
				Date d2 = sdf.parse("" + e2.get("tian"));
				return d1.compareTo(d2);
			}catch (Exception ex){

			}
			return 0;
		}).collect(Collectors.toList());
		for(Map map:chartList){
			Object obj1 = map.get("amt");
			Object obj2 = map.get("visit");
			obj1 = null == obj1 || "null".equals(obj1) ? "0" : obj1;
			obj2 = null == obj2 || "null".equals(obj2) ? "0" : obj2;
			map.put("订单金额",Double.parseDouble("" + obj1));
			map.put("访问量",Double.parseDouble("" + obj2));
		}
		return chartList;
	}

	public Map userAnalysis(Date dayStart, Date dayEnd) {
		Map retMap = new HashMap<>();
		int days = (int) DateUtil.betweenDay(dayStart, dayEnd, true);
		Calendar calendar = new GregorianCalendar();
		calendar.setTime(dayStart);
		calendar.add(Calendar.DAY_OF_MONTH, (0 - days));
		Date preDayStart = calendar.getTime();

		//访客数
		Long userCnt = sysLogMapper.findTodayUserCount(dayStart,dayEnd);
		Long preUserCnt = sysLogMapper.findTodayUserCount(preDayStart,dayStart);
		Map userMap = new HashMap();
		userMap.put("userCnt",userCnt);
		Double userPercent = mom(userCnt,preUserCnt);
		userMap.put("percent",String.format("%.2f",userPercent*100));
		userMap.put("add",userPercent>0);
		retMap.put("userMap",userMap);

		//访问数
		Long visCnt = sysLogMapper.findTodayVisitCount(dayStart, dayEnd);
		Long preVisCnt = sysLogMapper.findTodayVisitCount(preDayStart, dayStart);
		Map visMap = new HashMap();
		visMap.put("visCnt",visCnt);
		Double visPercent = mom(visCnt,preVisCnt);
		visMap.put("percent",String.format("%.2f",visPercent*100));
		visMap.put("add",visPercent>0);
		retMap.put("visMap",visMap);
		//新增用户数
		Long regCnt = sysUserMapper.findTodayRegCount(dayStart,dayEnd);
		Long preRegCnt = sysUserMapper.findTodayRegCount(preDayStart,dayStart);
		Map regMap = new HashMap();
		regMap.put("regCnt",regCnt);
		Double regPercent = mom(regCnt,preRegCnt);
		regMap.put("percent",String.format("%.2f",regPercent*100));
		regMap.put("add",regPercent>0);
		retMap.put("regMap",regMap);
		//成交用户数
		Long userOrderCnt = orderMapper.findTodayUserCount(dayStart,dayEnd);
		Long preUserOrderCnt = orderMapper.findTodayUserCount(preDayStart,dayStart);
		Map userOrderMap = new HashMap();
		userOrderMap.put("userOrderCnt",userOrderCnt);
		Double userOrderPercent = mom(userOrderCnt,preUserOrderCnt);
		userOrderMap.put("percent",String.format("%.2f",userOrderPercent*100));
		userOrderMap.put("add",userOrderPercent>0);
		retMap.put("userOrderMap",userOrderMap);
		//访客-支付转化率
		Double percent = userCnt == 0? 0l: userOrderCnt.doubleValue() / userCnt.doubleValue();
		Double prePercent = preUserCnt == 0?0l: preUserOrderCnt.doubleValue() / preUserCnt.doubleValue();
		Map percMap = new HashMap();
		percMap.put("perc",String.format("%.2f",percent*100));
		Double percPercent = mom(percent,prePercent);
		percMap.put("percent",String.format("%.2f",percPercent*100));
		percMap.put("add",percPercent>0);
		retMap.put("percMap",percMap);

		//充值用户数
		Long userRechargeCnt = orderRechargeMapper.findTodayUserCount(dayStart,dayEnd);
		Long preUserRechargeCnt = orderRechargeMapper.findTodayUserCount(preDayStart,dayStart);
		Map rechargeMap = new HashMap();
		rechargeMap.put("rechargeCnt",userRechargeCnt);
		Double rechargePercent = mom(userRechargeCnt,preUserRechargeCnt);
		rechargeMap.put("percent",String.format("%.2f",rechargePercent*100));
		rechargeMap.put("add",rechargePercent>0);
		retMap.put("rechargeMap",rechargeMap);

		//客单价
		List<Map> amtList = orderMapper.orderAmtByPayType(dayStart,dayEnd);
		Double amt = 0d;
		for(Map map:amtList){
			if(null != map){
				amt += Double.parseDouble(null == map.get("totalAmt")?"0":map.get("totalAmt").toString());
			}
		}
		Double avgAmt = 0 == userOrderCnt ? 0l: amt/userOrderCnt;

		List<Map> preAmtList = orderMapper.orderAmtByPayType(preDayStart,dayStart);
		Double preAmt = 0d;
		for(Map map:preAmtList){
			if(null != map){
				preAmt += Double.parseDouble(null == map.get("totalAmt")?"0":map.get("totalAmt").toString());
			}

		}
		Double preAvgAmt = 0 == preUserOrderCnt ? 0l: preAmt/preUserOrderCnt;

		Map avgAmtMap = new HashMap();
		avgAmtMap.put("avgAmt",String.format("%.2f",avgAmt));
		Double avgPercent = mom(avgAmt,preAvgAmt);
		avgAmtMap.put("percent",String.format("%.2f",avgPercent*100));
		avgAmtMap.put("add",avgPercent>0);
		retMap.put("avgAmtMap",avgAmtMap);

		//累计用户数
		Long userTotalCnt = sysUserMapper.findTodayRegCount(null,dayEnd);
		Long preUserTotalCnt = sysUserMapper.findTodayRegCount(null,dayStart);
		Map userTotalMap = new HashMap();
		userTotalMap.put("userTotalCnt",userTotalCnt);
		Double userTotalPercent = mom(userTotalCnt,preUserTotalCnt);
		userTotalMap.put("percent",String.format("%.2f",userTotalPercent*100));
		userTotalMap.put("add",userTotalPercent>0);
		retMap.put("userTotalMap",userTotalMap);

		//累计充值用户数
		Long userTotalRechargeCnt = orderRechargeMapper.findTodayUserCount(null,dayEnd);
		Long preUserTotalRechargeCnt = orderRechargeMapper.findTodayUserCount(null,dayStart);
		Map userTotalRechargeMap = new HashMap();
		userTotalRechargeMap.put("userTotalRechargeCnt",userTotalRechargeCnt);
		Double utrPercent = mom(userTotalRechargeCnt,preUserTotalRechargeCnt);
		userTotalRechargeMap.put("percent",String.format("%.2f",utrPercent*100));
		userTotalRechargeMap.put("add",utrPercent>0);
		retMap.put("userTotalRechargeMap",userTotalRechargeMap);

		//累计成交用户数
		Long userTotalOrderCnt = orderMapper.findTodayUserCount(null,dayEnd);
		Long preUserTotalOrderCnt = orderMapper.findTodayUserCount(null,dayStart);
		Map userTotalOrderMap = new HashMap();
		userTotalOrderMap.put("userTotalOrderCnt",userTotalOrderCnt);
		Double utoPercent = mom(userTotalOrderCnt,preUserTotalOrderCnt);
		userTotalOrderMap.put("percent",String.format("%.2f",utoPercent*100));
		userTotalOrderMap.put("add",utoPercent>0);
		retMap.put("userTotalOrderMap",userTotalOrderMap);
		return retMap;
	}

	public List<Map> userCharts(Date dayStart, Date dayEnd) {
		Map<String,Map> chartMap = new HashMap();
		//每天新增用户数
		//每天访客数
		//每天成交用户数
		//每天充值用户数
		List<Map> regCntList = sysUserMapper.findUserRegCount(dayStart,dayEnd);
		List<Map<String,Object>> visitCntList = sysLogMapper.findVisitCount(dayStart,dayEnd,"mysql");
		List<Map> userCntList = orderMapper.findUserCount(dayStart,dayEnd);
		List<Map> recCntList = orderRechargeMapper.findUserCount(dayStart,dayEnd);

		regCntList = CollectionUtil.isEmpty(regCntList)?new ArrayList<>():regCntList;
		visitCntList = CollectionUtil.isEmpty(visitCntList)?new ArrayList<>():visitCntList;
		userCntList = CollectionUtil.isEmpty(userCntList)?new ArrayList<>():userCntList;
		recCntList = CollectionUtil.isEmpty(recCntList)?new ArrayList<>():recCntList;
		for(Map visit:regCntList){
			Map map = new HashMap();
			String type = (String) visit.get("type");
			map.put("type",type);
			map.put("tian",visit.get("tian"));
			map.put("regCnt",visit.get("regCnt").toString());
			chartMap.put(type,map);
		}
		for(Map amt:visitCntList){
			String type = amt.get("type").toString();
			Map map = (Map)chartMap.get(type);
			if(null == map){
				map = new HashMap();
				map.put("type",type);
				map.put("tian",amt.get("tian").toString());
				map.put("regCnt","0");
				chartMap.put(type,map);
			}
			map.put("visit",amt.get("visit").toString());
		}

		for(Map amt:userCntList){
			String type = amt.get("type").toString();
			Map map = (Map)chartMap.get(type);
			if(null == map){
				map = new HashMap();
				map.put("type",type);
				map.put("tian",amt.get("tian").toString());
				map.put("regCnt","0");
				map.put("visit","0");
				chartMap.put(type,map);
			}
			map.put("userCnt",amt.get("userCnt").toString());
		}

		for(Map amt:recCntList){
			String type = amt.get("type").toString();
			Map map = (Map)chartMap.get(type);
			if(null == map){
				map = new HashMap();
				map.put("type",type);
				map.put("tian",amt.get("tian").toString());
				map.put("regCnt","0");
				map.put("visit","0");
				map.put("userCnt","0");
				chartMap.put(type,map);
			}
			map.put("recCnt",amt.get("recCnt").toString());
		}

		List<Map> chartList = chartMap.values().stream().sorted((e1,e2)->{
			try {
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				Date d1 = sdf.parse("" + e1.get("tian"));
				Date d2 = sdf.parse("" + e2.get("tian"));
				return d1.compareTo(d2);
			}catch (Exception ex){

			}
			return 0;
		}).collect(Collectors.toList());
		for(Map map:chartList){
			Object regCnt = map.get("regCnt");
			Object visit = map.get("visit");
			Object userCnt = map.get("userCnt");
			Object recCnt = map.get("recCnt");
			regCnt = null == regCnt?"0":regCnt;
			visit = null == visit?"0":visit;
			userCnt = null == userCnt?"0":userCnt;
			recCnt = null == recCnt?"0":recCnt;
			map.put("新增用户数",Long.parseLong("" + regCnt));
			map.put("访客数",Long.parseLong("" + visit));
			map.put("成交用户数",Long.parseLong("" + userCnt));
			map.put("充值用户数",Long.parseLong("" + recCnt));
		}
		return chartList;
	}

	public static Double mom(Long data1,Long data2){
		if(data1 == null || data2 == null){
			return 0.0;
		}
		if(data2 == 0){
			return 0d;
		}
		double percent = (data1.doubleValue()-data2.doubleValue())/data2.doubleValue();
		return percent;
	}

	public static Double mom(Double data1,Double data2){
		if(data1 == null || data2 == null){
			return 0.0;
		}
		if(data2 == 0){
			return 0d;
		}
		double percent = (data1.doubleValue()-data2.doubleValue())/data2.doubleValue();
		return percent;
	}

}
